<?php
/**
 * Copyright (c) 2006-2008, Julien PORTALIER
 * http://featherphp.googlecode.com/
 * 
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 */
define('UPLOAD_ERR_FILE_EXISTS',       'UPLOAD_ERR_FILE_EXISTS');
define('UPLOAD_ERR_FILE_NOT_UPLOADED', 'UPLOAD_ERR_FILE_NOT_UPLOADED');

class FileUpload
{
	/**
	 * Saves an uploaded file.
	 * Throws an UploadException exception on error.
	 * 
	 * @return Mixed Returns UPLOAD_ERR_OK if everything is alright.
	 * @param $name String
	 * @param $path_to String Where to save the file. Can be a specific filename or a directory.
	 * @param $overwrite Boolean[optional]
	 */
	function save($name, $path_to, $overwrite=false)
	{
		# uploaded?
		$ok = $this->exists($name);
		if ($ok !== UPLOAD_ERR_OK) {
			return $ok;
		}
		
		# where to save
		if (is_dir($path_to))
		{
			$_FILES[$name]['name'] = str_replace(array("\\", "'", '"', " "), array('', '-', '-', '_'), $_FILES[$name]['name']);
			$path_to .= DS.$_FILES[$name]['name'];
		}
		
		# overwrite?
		if (file_exists($path_to) and !$overwrite) {
			throw new UploadException(UPLOAD_ERR_FILE_EXISTS);
		}
		
		# saves uploaded file
		move_uploaded_file($_FILES[$name]['tmp_name'], $path_to);
		return UPLOAD_ERR_OK;
	}
	
	/**
	 * Saves many uploaded files at once.
	 * Throws an UploadException exception on error.
	 * 
	 * @return Mixed Returns UPLOAD_ERR_OK if everything is alright.
	 * @param $name String
	 * @param $path_to String Where to save the file. Must be a directory.
	 * @param $overwrite Boolean[optional]
	 */
	function save_many($name, $path_to, $overwrite=false)
	{
		$index = 0;
		
		# for each uploaded file
		while(true)
		{
			# uploaded?
			$ok = $this->exists($name, $index=null);
			if ($ok !== UPLOAD_ERR_OK) {
				return $ok;
			}
			
			# where to save
			if (is_dir($path_to))
			{
				$_FILES[$name]['name'] = str_replace(array("\\", "'", '"', " "), array('', '-', '-', '_'), $_FILES[$name]['name']);
				$path_to .= DS.$_FILES[$name]['name'];
			}
			
			# overwrite?
			if (file_exists($path_to) and !$overwrite) {
				throw new UploadException(UPLOAD_ERR_FILE_EXISTS);
			}
			
			# saves upload file
			move_uploaded_file($_FILES[$name]['tmp_name'][$index], $path_to);
			$index++;
		}
		return UPLOAD_ERR_OK;
	}
	
	/**
	 * Checks if an uploaded file has been uploaded.
	 * Throws an UploadException exception on error.
	 * 
	 * @return Mixed UPLOAD_ERR_OK if the file was uploaded, false otherwise.
	 * @param $name String
	 * @param $index Integer[optional] In case we want to check a specific file in the list.
	 */
	function exists($name, $index=null)
	{
		if (!empty($_FILES[$name]))
		{
			if (is_null($index))
			{
				# a single file
				if ($_FILES[$name]['error'] != UPLOAD_ERR_OK) {
					throw new UploadException($_FILES[$name]['error']);
				}
				if (!is_uploaded_file($_FILES[$name]['tmp_name'])) {
					throw new UploadException(UPLOAD_ERR_FILE_NOT_UPLOADED);
				}
			}
			else
			{
				# multiple files (batch upload)
				if (empty($_FILES[$name]['name'][$index])) {
					return false;
				}
				if ($_FILES[$name]['error'][$index] != UPLOAD_ERR_OK) {
					throw new UploadException($_FILES[$name]['error'][$index]);
				}
				if (!is_uploaded_file($_FILES[$name]['tmp_name'][$index])) {
					throw new UploadException(UPLOAD_ERR_FILE_NOT_UPLOADED);
				}
			}
			
			# upload exists
			return UPLOAD_ERR_OK;
		}
		
		# no such upload!
		return false;
	}
	
	function get_type($name)
	{
		return isset($_FILES[$name]['type']) ? $_FILES[$name]['type'] : null;
	}
	
	function get_filename($name)
	{
		return isset($_FILES[$name]['name']) ? $_FILES[$name]['name'] : null;
	}
	
	function get_tmp_filename($name)
	{
		return isset($_FILES[$name]['tmp_name']) ? $_FILES[$name]['tmp_name'] : null;
	}
}

class UploadException extends Exception
{
	function __construct($code)
	{
		switch($code)
		{
			case UPLOAD_ERR_NO_FILE:
				$mesg = t("No file was uploaded.", 'global.file');
				break;
			case UPLOAD_ERR_PARTIAL:
				$mesg = t("The file was only partially uploaded.", 'global.file');
				break;
			case UPLOAD_ERR_INI_SIZE:
				$mesg = sprintf(t("The uploaded file was too big (maximum is %s).", 'global.file'), ini_get('upload_max_filesize'));
				break;
			case UPLOAD_ERR_FORM_SIZE:
				$mesg = sprintf(t("The uploaded file was too big (maximum is %s).", 'global.file'), $_REQUEST['MAX_FILE_SIZE']);
				break;
			case UPLOAD_ERR_NO_TMP_DIR:
				$mesg = t("Server error: Missing a temporary folder.", 'global.file');
				break;
			case UPLOAD_ERR_CANT_WRITE:
				$mesg = t("Server error: unable to save uploaded file.", 'global.file');
				break;
			case UPLOAD_ERR_EXTENSION:
				$mesg = t("File extension refused.", 'global.file');
				break;
			case UPLOAD_ERR_FILE_NOT_UPLOADED:
				$mesg = t("Security alert: this file hasn't been uploaded!", 'global.file');
				break;
			case UPLOAD_ERR_FILE_EXISTS:
				$mesg = t("A file sharing this name already exists.", 'global.file');
				break;
			default:
				$mesg = t("An unknown file upload error occured.", 'global.file');	
		}
		parent::__construct($mesg, (double)$code);
	}
}
?>